#include "candevice.h"
#include <qDebug>
#include <QThread>

CanDevice::CanDevice()
{
    canDrive = new CanDrive();
    canopensdo = new CanOpenSdo();
}

void CanDevice:: printCANFrame(const Frame& frame)
{
    qDebug().nospace()\
        << "ID:" <<QString::number(frame.id,16) << " DLC:" << (int)frame.dlc << " Data:"\
        <<QString::number(frame.data[0], 16).toUpper()<<QString::number(frame.data[1], 16).toUpper() \
        <<QString::number(frame.data[2], 16).toUpper()<<QString::number(frame.data[3], 16).toUpper() \
        <<QString::number(frame.data[4], 16).toUpper()<<QString::number(frame.data[5], 16).toUpper() \
        <<QString::number(frame.data[6], 16).toUpper()<<QString::number(frame.data[7], 16).toUpper() ;
}

uint64_t CanDevice:: uint8ArrayToUint64( uint8_t *array)
{
    uint64_t value = 0;
    for (int i = 0; i < 8; ++i)
    {
        value |= static_cast<uint64_t>(array[i]) << (8 * i);
    }
    return value;
}

float CanDevice:: getSignalFromFrame(Frame frame, int16_t StartBit, int16_t BitLength, float Factor, int16_t Offset)
{
    uint64_t data = uint8ArrayToUint64(frame.data);
    return ((data >> StartBit) & ((uint64_t)(0x00000001 << BitLength) - 1)) * Factor + Offset;
}

int32_t CanDevice::canTransmitData(uint32_t id, uint8_t len, uint8_t *buf)
{
    return canDrive->canTransmitData(id ,len ,buf);
}

void CanDevice::canFrameProcess(Frame frame)
{
    static bool signal_flag = false ;

    switch(frame.id)
    {
    case 0x311:
    {
        param.acc_key = QString::number(getSignalFromFrame(frame, 0, 1, 1, 0) );
        param.emergency_pmu = QString::number(getSignalFromFrame(frame, 1, 1, 1, 0) );
        param.handle_detect = QString::number(getSignalFromFrame(frame, 2, 1, 1, 0) );
        param.left_detect = QString::number(getSignalFromFrame(frame, 3, 1, 1, 0) );
        param.right_detect = QString::number(getSignalFromFrame(frame, 4, 1, 1, 0) );
        signal_flag = true;
    }
    break;
    case 0x321:
    {
        param.current = QString::number(getSignalFromFrame(frame, 0, 16, 0.01f, -300) );
        param.vol = QString::number(getSignalFromFrame(frame, 16, 16, 0.01f, 0) );
        param.soc = QString::number(getSignalFromFrame(frame, 32, 8, 1, 0) );
        param.temprature = QString::number(getSignalFromFrame(frame, 40, 8, 1, -40) );
        param.bms_status = QString::number(getSignalFromFrame(frame, 48, 8, 1, 0) );
        param.bms_fault = QString::number(getSignalFromFrame(frame, 56, 8, 1, 0) );
        signal_flag = true;
    }
    break;
    case 0x312:
    {
        param.emergency_wdu = QString::number(getSignalFromFrame(frame, 2, 1, 1, 0) );
        signal_flag = true;
    }
    break;
    case 0x313:
    {
        //printCANFrame(frame);
        param.left_brush = QString::number(getSignalFromFrame(frame, 0, 2, 1, 0) );
        param.right_brush = QString::number(getSignalFromFrame(frame, 2, 2, 1, 0));
        param.waterpush = QString::number(getSignalFromFrame(frame, 4, 2, 1, 0));
        param.brushpush = QString::number(getSignalFromFrame(frame, 6, 2, 1, 0));
        param.suction = QString::number(getSignalFromFrame(frame, 8, 2, 1, 0));
        param.spraygear = QString::number(getSignalFromFrame(frame, 10, 2, 1, 0));
        param.clean_drain = QString::number(getSignalFromFrame(frame, 12, 1, 1, 0));
        param.dirty_drain = QString::number(getSignalFromFrame(frame, 13, 1, 1, 0));
        param.topledflash = QString::number(getSignalFromFrame(frame, 14, 1, 1, 0));
        param.frontled = QString::number(getSignalFromFrame(frame, 15, 1, 1, 0));
        param.clean = QString::number(getSignalFromFrame(frame, 16, 7, 1, 0));
        param.clean_empty = QString::number(getSignalFromFrame(frame, 23, 1, 1, 0));
        param.dirty = QString::number(getSignalFromFrame(frame, 24, 7, 1, 0));
        param.dirty_full = QString::number(getSignalFromFrame(frame, 31, 1, 1, 0));
        param.bud_status = QString::number(getSignalFromFrame(frame, 48, 8, 1, 0));
        signal_flag = true;
    }
    break;
    case 0x314:
    {
        param.clean_start_key = QString::number(getSignalFromFrame(frame, 2, 1, 1, 0) );
        param.suction_start_key = QString::number(getSignalFromFrame(frame, 3, 1, 1, 0) );
        param.crash = QString::number(getSignalFromFrame(frame, 4, 1, 1, 0) );
        param.pressure = QString::number(getSignalFromFrame(frame, 5, 1, 1, 0) );
        param.epf = QString::number(getSignalFromFrame(frame, 6, 1, 1, 0) );
        param.front_key = QString::number(getSignalFromFrame(frame, 7, 1, 1, 0) );
        param.back_key = QString::number(getSignalFromFrame(frame, 8, 1, 1, 0) );
        param.pause_key = QString::number(getSignalFromFrame(frame, 9, 1, 1, 0) );
        param.speaker = QString::number(getSignalFromFrame(frame, 10, 1, 1, 0) );
        param.front_led_key = QString::number(getSignalFromFrame(frame, 11, 1, 1, 0) );
        param.set_speed = QString::number(getSignalFromFrame(frame, 16, 8, 0.01, 0) );
        // param.hou_status = QString::number(getSignalFromFrame(frame, 48, 8, 1, 0) );
        signal_flag = true;
    }
    break;
    case 0x324:
    {
        param.nfc = QString::number(getSignalFromFrame(frame, 0, 56, 1, 0) );
        signal_flag = true;
    }
    break;
    case 0x315:
    {
        param.slope_angel = QString::number(getSignalFromFrame(frame, 0, 8, 1, 0) );
        signal_flag = true;
    }
    break;

    default:
        break;
    }
    if(signal_flag == true)
    {
        signal_flag = false;
        emit updateSignal(&param);
    }
}

bool CanDevice::ConnetCAN(void)
{
    if(!canDrive->OpenCAN())
    {
        return false;
    }
    else if(!canDrive->InitCAN(500))
    {
        return false;
    }
    else if(!canDrive->ClearBuffer())
    {
        return false;
    }
    else if(!canDrive->StartCAN())
    {
        return false;
    }
    connetStatus = true;
    return true;
}

bool CanDevice::CloseCAN(void)
{
    if(!canDrive->CloseCAN())
    {
        return false;
    }
    connetStatus = false;
    return true;
}

void CanDevice::canRecvData(void)
{
    qDebug()<<"CAN 接收线程启动";
    while(1)
    {
        canDrive->canReceiveData();
        if(!canDrive->frame_queue.isEmpty()) //队列非空
        {
            for(auto i = 0 ; i < canDrive->frame_queue.size(); i++)
            {
                auto frame = canDrive->frame_queue.dequeue();
                Frame frame1 ;
                frame1.id =   frame.ID ;
                frame1.dlc = frame.DataLen;
                std::memcpy(frame1.data ,frame.Data ,frame1.dlc);
                canFrameProcess(frame1);

                if(frame1.id == 0x503)
                {
                    printCANFrame(frame1);
                    if(canopensdo->canOpenSdoHandle(frame1.id ,frame1.data))
                    {
                        emit updateParam(&canopensdo->odParam);
                    }
                }
            }
        }
        QThread::msleep(10);
    }
}
void CanDevice::canSendData(void)
{
    qDebug()<<"CAN 发送线程启动";

    while(1)
    {
        QThread::msleep(1000);
    }
}
